package com.sduept.nwld.dataserver.manager.etl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.interceptor.Interceptors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sduept.bigdata.fault.common.ETLDAO;
import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultReportComponentDetail;
import com.sduept.bigdata.fault.interceptor.ProtectComponentInterceptor;
import com.sduept.bigdata.fault.manager.ComponentDictionaryManager;
import com.sduept.bigdata.fault.manager.ComponentManager;
import com.sduept.bigdata.fault.manager.FaultReportPersistManager;
import com.sduept.bigdata.fault.manager.FaultSourcePersistManager;
import com.sduept.bigdata.fault.manager.RequestTaskManager;
import com.sduept.bigdata.fault.report.etl.model.BxProtectDeviceAction;
import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.protection.ProtectionEquipment;
import com.sduept.cim.model.wires.BusbarSection;
import com.sduept.cim.model.wires.PowerTransformer;
import com.sduept.generator.ObjectId;
import com.sduept.nwld.dataserver.manager.cim.BxCimManager;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.model.edata.cim.bx.BxSubstation;
import com.sduept.utils.DateUtil;


@Service
public class ProtectionDeviceActionETLManager {

    @Autowired
    private ETLDAO eDao;

    @Autowired
    private CimManager cm;

    @Autowired
    private ComponentDictionaryManager cdm;
    @Autowired
    private BxCimManager bxCim;
    @Autowired
    private ComponentManager actionManager;
    @Autowired
    private FaultSourcePersistManager persistManager;
    @Autowired
    private FaultReportPersistManager reportManager;
    @Autowired
    private RequestTaskManager taskManager;

    public void receiveAndSaveAllData() {
        List<?> list = getAllSourceData();
        receiveAndSave(list);
    }

    public void receiveAndSavePartData(String date) {
        List<?> list = getSourceDatas(date);
        receiveAndSave(list);
    }

    /**
     * 根据故障查询动作元件
     *
     * @param record
     */
    public void getAndSaveActionData(FaultRecord record) {
        if (StringUtils.isNotEmpty(record.getEquipment_id())) {
            if ("线路".equals(record.getEtype())) {
                LineSegment acLineSegment = cm.getLineSegmentById(record.getEquipment_id());
                if (acLineSegment == null) {
                    return;
                }
                if (StringUtils.isNotEmpty(acLineSegment.getStartST())) {
//					this.sessionContext.getBusinessObject(ProtectionDeviceActionETLManager.class).getAndSaveActionData(acLineSegment.getStartST(),record);
                    getAndSaveActionData(acLineSegment.getStartST(), record);
                }
                if (StringUtils.isNotEmpty(acLineSegment.getEndST())) {
//					this.sessionContext.getBusinessObject(ProtectionDeviceActionETLManager.class).getAndSaveActionData(acLineSegment.getEndST(),record);
                    getAndSaveActionData(acLineSegment.getEndST(), record);
                }
            } else if ("变压器".equals(record.getEtype())) {
                PowerTransformer powerTransformer = cm.getPowerTransformersById(record.getEquipment_id());
//				this.sessionContext.getBusinessObject(ProtectionDeviceActionETLManager.class).getAndSaveActionData(powerTransformer.getSubId(),record);
                getAndSaveActionData(powerTransformer.getSubId(), record);
            } else if ("母线".equals(record.getEtype())) {
                BusbarSection busbarSection = cm.getBusbarSectionsById(record.getEquipment_id());
//				this.sessionContext.getBusinessObject(ProtectionDeviceActionETLManager.class).getAndSaveActionData(busbarSection.getSubId(),record);
                getAndSaveActionData(busbarSection.getSubId(), record);
            }
        }
    }

    /**
     * 根据故障和变电站Id 查询保护动作事件并存储
     *
     * @param date
     */
    public void getAndSaveActionData(String stationId, FaultRecord record) {
        List<FaultReportComponentDetail> result = getActionData(stationId, record);
        reportManager.saveFaultReportActionComponet(record.getId(), stationId, result);
        cdm.saveComponentDict(result);
        if (result == null || result.size() == 0) {
            taskManager.generateActionRequestTask(record, stationId);
        }
        persistManager.saveFaultSourceUploadInfo(record);
    }

    /**
     * 根据故障和变电站Id 查询保护动作事件
     *
     * @param stationId
     * @param record    故障档案信息表
     * @return
     */
    @Interceptors(ProtectComponentInterceptor.class)
    public List<FaultReportComponentDetail> getActionData(String stationId, FaultRecord record) {
        List<FaultReportComponentDetail> result = new ArrayList<>();//故障报告元件动作详情（多个）
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(record.getFaultTime());
        calendar.add(Calendar.MINUTE, -1);//1分钟之前
        Date start = calendar.getTime();
        calendar.add(Calendar.MINUTE, 2);//2分钟之后
        Date end = calendar.getTime();
        //获取时间区间为[start,end]的所有数据（保护装置动作告警表t_bx_protect_device_action）
        List<?> list = getSourceDataByDate(DateUtil.getStringDate(start, DateUtil.pattern_ymdhms), DateUtil.getStringDate(end, DateUtil.pattern_ymdhms));
        ProtectEquipmentSave equipmentSave = new ProtectEquipmentSave(list);
        //（保护装置动作告警）提取信息，存入BxProtectDeviceAction实体中，并形成list数组。
        List<BxProtectDeviceAction> list2 = equipmentSave.getResult();
        //保护装置动作信息组、设备故障信息、变电站id
        result = actionManager.getFaultReportComponentDetailInfos(list2, record, stationId);
        return result;
    }

    public List<?> getSourceDataByDate(String start, String end) {
        List<?> result = eDao.query("select mName,mMsg,mProtectName,mRID,mEventStartTime,mStartMs,mReceviceTime,mFinishMs,mFun,"
                + "mFaultType,mFaultMsg,m103Group,m103Item,pt_id,mStationID,mValue from t_bx_protect_device_action where mEventStartTime between"
                + " '" + start + "' and '" + end + "' order by mEventStartTime asc ,mStartMs asc ");
        return result;
    }

    public List<?> getAllSourceData() {
        List<?> result = eDao.query("select mName,mMsg,mProtectName,mRID,mEventStartTime,mStartMs,mReceviceTime,mFinishMs,mFun,"
                + "mFaultType,mFaultMsg,m103Group,m103Item,pt_id,mStationID,mValue from t_bx_protect_device_action ");
        return result;
    }

    public List<?> getSourceDatas(String date) {
        String sql = "select mName,mMsg,mProtectName,mRID,mEventStartTime,mStartMs,mReceviceTime,mFinishMs,mFun,"
                + "mFaultType,mFaultMsg,m103Group,m103Item,pt_id,mStationID,mValue from t_bx_protect_device_action where update_time=";
        List<?> result = eDao.query(sql + "'" + date + "'");
        return result;
    }

    public void receiveAndSave(List<?> list) {
        ProtectEquipmentSave equipmentSave = new ProtectEquipmentSave(list);
        equipmentSave.getResult();
    }

    public class ProtectEquipmentSave {
        private List<?> list;//（多个保护装置动作告警t_bx_protect_device_action）
        private Map<String, ProtectionEquipment> mNameMap = new HashMap<String, ProtectionEquipment>();
        private Map<String, BxSubstation> bxMap = new HashMap<String, BxSubstation>();

        public ProtectEquipmentSave(List<?> list) {
            super();
            this.list = list;
            init();
        }

        public void init() {
            List<ProtectionEquipment> protectionEquipments = cm.listAllProtectionEquipments();
            for (ProtectionEquipment equipemnt : protectionEquipments) {
                if (StringUtils.isNotEmpty(equipemnt.getSubId())) {
                    mNameMap.put(equipemnt.getName() + equipemnt.getSubId(), equipemnt);//{保护设备名称+站id，二次保护设备实体}
                }
            }
            //BxSubstation：保信系统变电站
            List<BxSubstation> bxSubstations = bxCim.listAllBxSubstations();
            for (BxSubstation station : bxSubstations) {
                if (StringUtils.isNotEmpty(station.getCimName())) {
                    bxMap.put(station.getMname(), station);//{名称，变电站实体}
                }
            }
        }

        public List<BxProtectDeviceAction> getResult() {
            Set<String> set = new HashSet<>();
            //保护设备(装置)动作告警信息（list）
            List<BxProtectDeviceAction> equipments = new ArrayList<BxProtectDeviceAction>();
            for (Object obj : list) {
                Object[] objs = (Object[]) obj;
                for (int i = 0; i < objs.length; i++) {
                    if (objs[i] != null && "null".equals(objs[i].toString())) {
                        objs[i] = null;
                    }
                }
                if (objs[15] != null) {
                    if ("复归".equals(objs[15].toString())) {
                        continue;
                    }
                }
                if (objs[0] != null) {
                    BxProtectDeviceAction action = new BxProtectDeviceAction();
                    action.setmName(objs[0].toString());
                    if (objs[1] != null) action.setmMsg(objs[1].toString());
                    if (objs[2] != null) action.setmProtectName(objs[2].toString());
                    if (objs[3] != null)
                        action.setmRID(objs[3].toString());
                    else { //如果没有自动生成
                        action.setmRID(ObjectId.get().toString());
                    }
                    if (objs[4] != null)
                        action.setmEventStartTime(DateUtil.getDateByString(objs[4].toString(), DateUtil.pattern_ymdhms));
                    if (objs[5] != null) action.setmStartMs((int) objs[5]);
                    if (objs[6] != null)
                        action.setmReceviceTime(DateUtil.getDateByString(objs[6].toString(), DateUtil.pattern_ymdhms));
                    if (objs[7] != null) action.setmFinishMs((int) objs[7]);
                    if (objs[8] != null) action.setmFun(objs[8].toString());
                    if (objs[9] != null) action.setmFaultType(objs[9] == null ? null : objs[9].toString());
                    if (objs[10] != null) action.setmFaultMsg(objs[10] == null ? null : objs[10].toString());
                    if (objs[11] != null) action.setM103Group((int) objs[11]);
                    if (objs[12] != null) action.setM103Item((int) objs[12]);
                    if (objs[15] != null) action.setmValue(objs[15].toString());
                    if (objs[14] != null) {
                        BxSubstation bxSubstation = bxMap.get(objs[14].toString());
                        if (bxSubstation != null) {
                            action.setmStationID(bxSubstation.getCimId());
                        }
                        ProtectionEquipment equipment = mNameMap.get(action
                                .getmProtectName() + action.getmStationID());
                        if (equipment != null) {
                            if (!StringUtils.isEmpty(equipment.getId())) {
                                action.setmDevID(equipment.getId());
                            }
                            if (!StringUtils.isEmpty(equipment.getPtId())) {
                                action.setPt_id(equipment.getPtId());
                            }
                        }
                    }
                    String sign = getSignByAction(action);
                    if (!set.contains(sign)) {
                        set.add(sign);
                        equipments.add(action);
                    }
                }
            }
            return equipments;
        }
    }

    private String getSignByAction(BxProtectDeviceAction action) {
        String s = action.getmFinishMs() + action.getmDevID() + action.getmFaultMsg() + action.getmFaultType() + action.getmFdevID() + action.getmFun() + action.getmMsg() + action.getmName() + action.getmProtectName() + action.getmStationID()
                + action.getmValue() + action.getPt_id() + action.getmStartMs() + action.getmEventStartTime().getTime();
        return s;
    }
}
